package lock;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author: li_jian
 * @version: 1.0
 * @date: 2020/6/21 22:50
 * @description： Lock 实现生产者消费者
 */
public class TestProductAndConsumerWithLock {

    public static void main(String[] args) {
        Clerk2 Clerk2 = new Clerk2();

        Product2 Product2 = new Product2(Clerk2);
        Consumer2 Consumer2 = new Consumer2(Clerk2);

        new Thread(Product2, "生产者 A").start();
        new Thread(Consumer2, "消费者 B").start();
    }
}

//营业员
class Clerk2 {
    private int product = 0;

    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();

    //进货
    public void get() {
        lock.lock();//加锁
        try {
            if (product >= 1) {
                System.out.println("产品已满！");

                try {
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            System.out.println(Thread.currentThread().getName() + " : " + ++product);
            condition.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();//释放锁
        }
    }

    //卖货
    public void sale() {
        lock.lock();//加锁
        try {
            if (product <= 0) {
                System.out.println("缺货！");

                try {
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            System.out.println(Thread.currentThread().getName() + " : " + --product);
            condition.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();//释放锁
        }
    }
}


class Product2 implements Runnable {

    private Clerk2 Clerk2;

    public Product2(Clerk2 Clerk2) {
        this.Clerk2 = Clerk2;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            Clerk2.get();
        }
    }
}

class Consumer2 implements Runnable {

    private Clerk2 Clerk2;

    public Consumer2(Clerk2 Clerk2) {
        this.Clerk2 = Clerk2;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            Clerk2.sale();
        }
    }
}
